package com.open.capacity.common.util.skf;


import com.sun.jna.Structure;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;

public class Struct_ECCSIGNATUREBLOB extends Structure {
    // ECC签名数据结构
  /*
  typedef struct Struct_ECCSIGNATUREBLOB{
    BYTE	r[ECC_MAX_XCOORDINATE_BITS_LEN/8];
    BYTE	s[ECC_MAX_YCOORDINATE_BITS_LEN/8];
  } ECCSIGNATUREBLOB, *PECCSIGNATUREBLOB;
*/
    public byte[] rb = new byte[32];
    public byte[] r = new byte[32];
    public byte[] sb = new byte[32];
    public byte[] s = new byte[32];

    public static class ByReference extends Struct_ECCSIGNATUREBLOB implements Structure.ByReference {
    }

    public static class ByValue extends Struct_ECCSIGNATUREBLOB implements Structure.ByValue {
    }

    public byte[] get_r() {
        return r;
    }

    public byte[] get_s() {
        return s;
    }

    // https://blog.csdn.net/daihuimaozideren/article/details/81072738
    // 30 + LEN1 + 02 + LEN2 + 00 (optional) + r + 02 + LEN3 + 00(optional) + s
    // 当r或s的第1字节大于0x80时，需要在r或s前加1字节0x00。
    public String get_sign() {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] h = {48, 68};

        byte[] r_h = {02, 32};
        byte[] s_h = {02, 32};
        byte[] r_h2 = {02, 33, 00};
        byte[] s_h2 = {02, 33, 00};
        boolean flag_r = false;
        boolean flag_s = false;

        String sign_b64 = "";

        if (r[0] < 0) {
            Util.red("r0 < 0 = " + r[0]);
            flag_r = true;
            h[1] = 69; //{48,69};
        }
        if (s[0] < 0) {
            Util.red("s0 < 0 = " + s[0]);
            flag_s = true;
            h[1] = 69; //{48,69};
        }
        if ((r[0] < 0) && (s[0] < 0)) {
            h[1] = 70; //{48,69};
        }

        try {
            baos.write(h);

            if (flag_r) {
                byte[] r_temp = Util.byteMerger(r_h2, r);
                baos.write(r_temp);
            } else {
                byte[] r_temp = Util.byteMerger(r_h, r);
                baos.write(r_temp);
            }

            if (flag_s) {
                byte[] s_temp = Util.byteMerger(s_h2, s);
                baos.write(s_temp);
            } else {
                byte[] s_temp = Util.byteMerger(s_h, s);
                baos.write(s_temp);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        //byte[] r_s_temp = Util.byteMerger(r_temp, s_temp);
        //byte[] sign = Util.byteMerger(h, r_s_temp);
        byte[] sign = baos.toByteArray();
        Util.red("baos = " + Util.bytesToHex(sign));
        sign_b64 = Base64.getEncoder().encodeToString(sign);
        return sign_b64;
    }

    public int parse_from_p1(String sign_p1_base64) {
        if (sign_p1_base64.length() == 0) {
            return -1;
        }
        byte[] sign_decoded = Base64.getDecoder().decode(sign_p1_base64);
        Util.red("hex sign_p1 = " + Util.bytesToHex(sign_decoded));

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] r_temp = new byte[32];
        //r0 < 0 = -93
        //s0 < 0 = -19
        //baos = 3046022100a3402e5a90b05a1f5b559c5c419fd1d4c066f6bc04725ef6804045f3f5e7db32022100ed47788ce825f2b6dea62139e9c6f9adb91c71e0358e5e60b55768e9fbc20aa2

        //int len_rs =  sign_decoded[1];
        //System.out.println("len_rs = " +  len_rs);

        int leng_r = sign_decoded[3];
        Util.red("leng_r = " + leng_r);

        // 30 leng_r+leng_s | 02 leng_r(x00 _32_) | 02 leng_s( x00 _32_)
        int leng_s = sign_decoded[2 + 1 + leng_r + 2];
        Util.red("leng_s = " + leng_s);

        for (int i = 0; i < 32; i++) {
            if (leng_r == 32) {
                baos.write(sign_decoded[4 + i]);
            }
            if (leng_r == 33) {
                baos.write(sign_decoded[5 + i]);
            }
        }
        r = baos.toByteArray();
        //System.out.println("hex r = " +  Util.bytesToHex(r));
        Util.red("hex r = " + Util.bytesToHex(r));
        baos.reset();

        int index_s = sign_decoded.length - 32;
        for (int i = 0; i < 32; i++) {
            baos.write(sign_decoded[index_s + i]);
        }
        s = baos.toByteArray();
        //System.out.println("hex s = " +  Util.bytesToHex(s));
        Util.red("hex s = " + Util.bytesToHex(s));
        baos.reset();

        return 1;
    }

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"rb", "r", "sb", "s"});
    }
}

